package cn.bisoft.java.util.common;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class ReflectUtil {

	private ReflectUtil() {
	}

	public static Set<Constructor> getConstructors(Class<?> clz) {

		Set<Constructor> constructors = new HashSet<Constructor>();

		constructors.addAll(Arrays.asList(clz.getConstructors()));

		constructors.addAll(Arrays.asList(clz.getDeclaredConstructors()));

		return constructors;
	}

	public static Set<Method> getMethods(Class<?> clz) {

		Set<Method> methods = new HashSet<Method>();

		methods.addAll(Arrays.asList(clz.getMethods()));

		methods.addAll(Arrays.asList(clz.getDeclaredMethods()));

		return methods;
	}

	public static Set<Class> getClasses(Class<?> clz) {

		Set<Class> classes = new HashSet<Class>();

		Class<?>[] interfaces = clz.getInterfaces();

		Class<?> superClass = clz.getSuperclass();

		classes.addAll(Arrays.asList(interfaces));

		classes.add(superClass);

		return classes;
	}

	public static Set<Method> getAllMethods(Class<?> clz) {
		Set<Class> classes = getClasses(clz);
		Set<Method> methods = getMethods(clz);

		for (Class clazz : classes) {
			methods.addAll(getMethods(clazz));
		}

		return methods;
	}

	public static Object newInstance(String className) {
		try {
			Constructor constructor = getNoParamsConstructor(getContextClassLoader()
					.loadClass(className));

			constructor.setAccessible(true);

			return constructor.newInstance((Object[]) null);

		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

	public static ClassLoader getContextClassLoader() {
		return Thread.currentThread().getContextClassLoader();
	}

	public static ClassLoader getSystemClassLoader() {
		return ClassLoader.getSystemClassLoader();
	}

	public static Constructor getNoParamsConstructor(Class<?> clz) {
		for (Constructor constructor : getConstructors(clz)) {
			if (0 == constructor.getParameterTypes().length) {
				return constructor;
			}
		}

		return null;
	}

	// *********** BEGIN TEST *****************

	public static void main(String[] args) {
		Set<Method> methods = ReflectUtil.getAllMethods(ReflectUtil.class);

		for (Method method : methods) {
			System.out.println(method.getDeclaringClass().getName() + " | "
					+ method.getName() + " | "
					+ method.getParameterTypes().length);
		}
	}

	// *********** END   TEST  *****************

}

